package com.jie.eclipse.pan.xml;

import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;

import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.jie.eclipse.pan.data.BaseDataEntity;
import com.jie.eclipse.pan.utils.StringHelper;
/**
 * XML 基本配置对象
 * 
 * @author yanjie
 * 
 */
public class XMLConfig implements Cloneable 
{
	public final static String XMLHEADER = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
	private BaseDataEntity dataRecord = null;
	
	public BaseDataEntity getDataRecord() {
		if(this.dataRecord == null)
			this.dataRecord = new BaseDataEntity();
		return dataRecord;
	}

	public XMLConfig()
	{
	}

	protected String strId = ""; // 节点ID

	protected String strNodeName = "";

	protected String strNodeValue = "";

	protected Hashtable extAttrList = null;// new Hashtable();

	// / <summary>
	// / 加载配置文件
	// / </summary>
	// / <param name="strConfigPath"></param>
	// / <returns></returns>
	public boolean LoadConfig(Node xmlNode)
	{
		// 枚举节点自身属性
		if (true)
		{
			strNodeName = xmlNode.getNodeName();
			strNodeValue = xmlNode.getNodeValue();
			if (strNodeValue == null)
				strNodeValue = "";
		}

		// 枚举所有的属性
		if (true)
		{
			NamedNodeMap attrs = xmlNode.getAttributes();
			if (attrs != null)
			{
				for (int i = 0; i < attrs.getLength(); i++)
				{
					Node attrNode = attrs.item(i);
					if (attrNode != null)
						OnSetProperty(attrNode.getNodeName().toUpperCase(), attrNode.getNodeValue());
				}
			}

		}
		// 枚举所有的子结点
		if (true)
		{
			NodeList nodes = xmlNode.getChildNodes();
			if (nodes != null)
			{
				for (int i = 0; i < nodes.getLength(); i++)
				{
					Node childNode = nodes.item(i);
					if (childNode != null)
					{
						String strNodeName = childNode.getNodeName().toUpperCase();
						if (StringHelper.Compare(strNodeName, "#TEXT", true) == 0)
						{
							strNodeValue += childNode.getNodeValue();
							continue;
						}

						if (StringHelper.Compare(strNodeName, "#CDATA-SECTION", true) == 0)
						{
							strNodeValue += childNode.getNodeValue();
							continue;
						}

						if (strNodeName.indexOf("#") == 0)
						{
							continue;
						}

						OnLoadNode(strNodeName, childNode);
					}
				}
			}

		}

		return true;
	}

	/**
	 * 加载XML节点
	 * @param strName
	 * @param xmlNode
	 */
	protected void OnLoadNode(String strName, Node xmlNode)
	{
	}

	// / <summary>
	// / 保存配置文件
	// / </summary>
	// / <param name="strConfigPath"></param>
	// / <returns></returns>
	// public boolean SaveConfig(XmlWriter xmlWriter)
	// {
	// return true;
	// }

	public void OnSetProperty(String strName, String strValue)
	{
		if (strName.compareToIgnoreCase(TagHelper.ID) == 0)
		{
			strId = strValue;
			return;
		}

		// 不明属性
		if (extAttrList == null)
			extAttrList = new Hashtable();
		extAttrList.put(strName.toUpperCase(), strValue);
		setExtDataRecordValue(strName,strValue);
	}

	/**
	 * 获取节点编号
	 * @return
	 */
	public String getID()
	{
		return strId;
	}

	/**
	 * 设置节点编号
	 * @param value
	 */
	public void setID(String value)
	{
		strId = value;
	}

	/**
	 * 获取节点名称
	 * @return
	 */
	public String getNodeName()
	{
		return strNodeName;
	}

	/**
	 * 设置节点名称
	 * @param value
	 */
	public void setNodeName(String value)
	{
		strNodeName = value;
	}

	/**
	 * 获取节点值
	 * @return
	 */
	public String getNodeValue()
	{
		return strNodeValue;
	}

	/**
	 * 设置节点值
	 * @param value
	 */
	public void setNodeValue(String value)
	{
		strNodeValue = value;
	}

	/**
	 * 判断是否存在指定键值
	 * @param strKey
	 * @return
	 */
	public boolean IsContainsKey(String strKey)
	{
		strKey = strKey.toUpperCase();
		if (extAttrList != null)
		{
			return extAttrList.containsKey(strKey);
		}
		return false;
	}

	/**
	 * @param strKey
	 * @param strDefault
	 * @return
	 */
	public String GetExtValue(String strKey, String strDefault)
	{
		strKey = strKey.toUpperCase();
		if (extAttrList != null)
			if (extAttrList.containsKey(strKey))
			{
				Object objValue = GetExtValue(strKey);
				if (StringHelper.IsNullOrEmpty(StringHelper.getValue(objValue)))
				{
					return strDefault;
				}
				try
				{
					if(objValue instanceof String[] && ((String[])objValue).length > 0){
						return ((String[])objValue)[0].trim(); 
					}
					
					return StringHelper.getValue(objValue);
				}
				catch (Exception ex)
				{
					return strDefault;
				}
			}
		return strDefault;
		
		
	}
	
	public Object GetExtValue(String strKey)
	{
		strKey = strKey.toUpperCase();
		if (extAttrList != null)
			if (extAttrList.containsKey(strKey))
			{
				return extAttrList.get(strKey);
			}
		return null;
	}

	/**
	 * @param strKey
	 * @param nDefault
	 * @return
	 */
	public int GetExtValue(String strKey, int nDefault)
	{
		try
		{
			Integer tempValue = new Integer(nDefault);
			return Integer.parseInt(GetExtValue(strKey, tempValue.toString()));
		}
		catch (Exception ex)
		{
			return nDefault;
		}
	}

	/**
	 * @param strKey
	 * @param nDefault
	 * @return
	 */
	public long GetExtValue(String strKey, long nDefault)
	{
		try
		{
			Long nTempValue = new Long(nDefault);
			return Long.parseLong(GetExtValue(strKey, nTempValue.toString()));
		}
		catch (Exception ex)
		{
			return nDefault;
		}

	}

	/**
	 * @param strKey
	 * @param bDefault
	 * @return
	 */
	public boolean GetExtValue(String strKey, boolean bDefault)
	{
		try
		{
			return Boolean.parseBoolean(GetExtValue(strKey, bDefault ? "True" : "False"));
		}
		catch (Exception ex)
		{
			return bDefault;
		}
	}

	/**
	 * 设置附加属性
	 * 
	 * @param strKey
	 * @param strValue
	 */
	public void SetExtValue(String strKey, String strValue)
	{
		if (extAttrList == null)
			extAttrList = new Hashtable();
		extAttrList.put(strKey.toUpperCase(), strValue);
		
		setExtDataRecordValue(strKey,strValue);
	}
	
	public void SetExtValue(String strKey, Object strValue)
	{
		if (extAttrList == null)
			extAttrList = new Hashtable();
		extAttrList.put(strKey.toUpperCase(), strValue);
		
		setExtDataRecordValue(strKey,strValue);
	}
	
	public void setExtDataRecordValue(String strKey, Object strValue){
		this.getDataRecord().spov(strKey, strValue);
	}

	/**
	 * 删除扩展属性
	 * @param strKey
	 */
	public void RemoveExtValue(String strKey)
	{
		if (extAttrList == null)
			return ;
		
		extAttrList.remove(strKey.toUpperCase());
		
		if(this.getDataRecord() == null)
			return;
		this.getDataRecord().RemoveParam(strKey);
	}
	
	
	/**
	 * @param strValue
	 * @param bDefault
	 * @return
	 */
	public static boolean GetValue(String strValue, boolean bDefault)
	{
		try
		{
			return Boolean.parseBoolean(strValue);
		}
		catch (Exception ex)
		{
			return bDefault;
		}

	}

	/**
	 * @param strValue
	 * @param fDefault
	 * @return
	 */
	public static double GetValue(String strValue, double fDefault)
	{
		try
		{
			if (strValue.indexOf("%") == (strValue.length() - 1))
			{
				strValue = strValue.replaceAll("%", "");
				return Double.parseDouble(strValue) / 100;
			}
			else
				return Double.parseDouble(strValue);
		}
		catch (Exception ex)
		{
			return fDefault;
		}
	}

	public static float GetValue(String strValue, float fDefault)
	{
		try
		{
			return Float.parseFloat(strValue);
		}
		catch (Exception ex)
		{
			return fDefault;
		}
	}

	// / <summary>
	// / 获取数字
	// / </summary>
	// / <param name="strValue"></param>
	// / <param name="bDefault"></param>
	// / <returns></returns>
	public static int GetValue(String strValue, int nDefault)
	{
		try
		{
			return Integer.parseInt(strValue);
		}
		catch (Exception ex)
		{
			return nDefault;
		}
	}

	/**
	 * 直接设置属性及值
	 * 
	 * @param strName
	 * @param strValue
	 */
	public void SetValue(String strName, String strValue)
	{
		strName = strName.toUpperCase();
		if (StringHelper.Length(strValue) != 0)
		{
			if (extAttrList == null)
				extAttrList = new Hashtable();
			extAttrList.put(strName, strValue);
			
			setExtDataRecordValue(strName,strValue);
		}
		else
		{
			if (extAttrList != null)
			{
				extAttrList.remove(strName);
			}
		}
	}
	
	/**
	 * 直接设置属性及值
	 * 
	 * @param strName
	 * @param strValue
	 */
	public void SetValue(String strName, Object objvalue)
	{
		strName = strName.toUpperCase();
		if (objvalue != null)
		{
			if (extAttrList == null)
				extAttrList = new Hashtable();
			extAttrList.put(strName, objvalue);
			
			setExtDataRecordValue(strName,objvalue);
		}
		else
		{
			if (extAttrList != null)
			{
				extAttrList.remove(strName);
			}
		}
	}

	/**
	 * 保存节点的信息
	 * 
	 * @param xmlWriter
	 * @return boolean
	 */
	public boolean Save(SimpleXMLWriter xmlWriter, boolean bSaveChild)
	{
		return Save(xmlWriter,strNodeName,bSaveChild);
	}

	
	/**
	 * 保存节点的信息
	 * 
	 * @param xmlWriter
	 *            SimpleXMLWriter
	 * @return boolean
	 */
	public boolean Save(SimpleXMLWriter xmlWriter,String strNodeName, boolean bSaveChild)
	{
		if (StringHelper.Length(strNodeName) != 0)
		{
			xmlWriter.WriteStartElement(strNodeName);
			// 保存当前属性
			if (!SavePropertys(xmlWriter))
				return false;

			// 保存子节点信息
			if (bSaveChild)
			{
				if (!SaveChildNodes(xmlWriter))
					return false;
			}

			xmlWriter.WriteEndElement();

		}
		return true;
	}
	
	/**
	 * 保存XML配置，同时保存子节点
	 * 
	 * @param xmlWriter
	 * @return
	 */
	public boolean Save(SimpleXMLWriter xmlWriter)
	{
		return Save(xmlWriter, true);
	}

	/**
	 * 保存子节点信息
	 * 
	 * @param xmlWriter
	 *            SimpleXMLWriter
	 * @return boolean
	 */
	protected boolean SaveChildNodes(SimpleXMLWriter xmlWriter)
	{
		return true;
	}

	/**
	 * 保存节点的属性
	 * 
	 * @param xmlWriter
	 *            SimpleXMLWriter
	 * @return boolean
	 */
	protected boolean SavePropertys(SimpleXMLWriter xmlWriter)
	{
		if (StringHelper.Length(strId) != 0)
		{
			xmlWriter.WriteAttributeString(TagHelper.ID, strId);
		}

		if (extAttrList != null)
		{
			Enumeration enumeration = extAttrList.keys();
			while (enumeration.hasMoreElements())
			{
				String strKey = (String) enumeration.nextElement();
				String strValue = (String) extAttrList.get(strKey);
				if (!StringHelper.IsNullOrEmpty(strValue))
					xmlWriter.WriteAttributeString(strKey, strValue);
			}
		}

		if (!StringHelper.IsNullOrEmpty(strNodeValue))
		{
			String strTemp = strNodeValue.replace("\r", "");
			strTemp = strTemp.replace("\n", "");
			strTemp = strTemp.replace("&#xD;", "");
			strTemp = strTemp.replace("&#xA;", "");
			strTemp = strTemp.replace("\t", "");
			strTemp = strTemp.replace(" ", "");
			if (!StringHelper.IsNullOrEmpty(strTemp))
				xmlWriter.WriteCDATA(strNodeValue);
		}

		return true;
	}

	/**
	 * 获取所有的扩展属性
	 * 
	 * @return
	 */
	public Hashtable getExtAttrs()
	{
		return extAttrList;
	}

	
	/**
	 * 节点加载XML
	 * @param strXML
	 * @return
	 */
	public boolean LoadXML(String strXML)
	{
		return XMLConfig.LoadFromXML(strXML, this);
	}
	
	/**
	 * 加载配置
	 * @param strXML
	 * @param xmlConfig
	 * @return
	 */
	public static boolean LoadFromXML(String strXML, XMLConfig xmlConfig)
	{
		try
		{
			InputSource is = new InputSource(new java.io.StringReader(strXML));
			DOMParser parser = new DOMParser();
			parser.parse(is);
			Document doc = parser.getDocument();

			return xmlConfig.LoadConfig(doc.getDocumentElement());
		}
		catch (Exception ex)
		{
			System.out.println(StringHelper.Format("加载XML配置发生错误:%1$s", ex.getMessage()));
			return false;
		}
	}

	/**
	 * 加载配置
	 * 
	 * @param strXML
	 * @param xmlConfig
	 * @return
	 */
	public static boolean LoadFromFile(String strConfigPath, XMLConfig xmlConfig)
	{
		try
		{
			DOMParser parser = new DOMParser();
			parser.parse(strConfigPath);
			Document doc = parser.getDocument();
			return xmlConfig.LoadConfig(doc.getDocumentElement());
		}
		catch (Exception ex)
		{
			System.out.println(StringHelper.Format("加载XML配置发生错误:%1$s", ex.getMessage()));
			return false;
		}
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#clone()
	 */
	public Object clone()
	{
		Object obj = CreateCloneObject();
		if (obj == null)
			return null;

		CloneCopy(obj);
		return obj;
	}

	/**
	 * 建立要克隆的对象
	 * @return
	 */
	protected Object CreateCloneObject()
	{
		return new XMLConfig();
	}

	protected void CloneCopy(Object dst)
	{
		XMLConfig obj = (XMLConfig) dst;
		obj.setID(this.getID());
		obj.setNodeName(this.getNodeName());
		obj.setNodeValue(this.getNodeValue());

		if (extAttrList != null)
		{
			Enumeration enumeration = extAttrList.keys();
			while (enumeration.hasMoreElements())
			{
				String strKey = (String) enumeration.nextElement();
				Object strValue = extAttrList.get(strKey);
				obj.SetExtValue(strKey, strValue);
			}
		}
	}
	
	
	public void Reset()
	{
		this.extAttrList = null;
		this.strId = "";
		this.strNodeName = "";
		this.strNodeValue = "";
		
	}
	
	/**
	 * @param strParamName
	 * @return
	 * 获取字符型参数 簡寫
	 */
	public String gpsv(String strParamName){
		return this.GetExtValue(strParamName,"");
	}
	
	public boolean isNullOrEmpty(String key){
		if(this.gpov(key) == null)
			return true;
		
		if(this.gpsv(key).length() == 0)
			return true ;
		return false;
	}
	
	/**
	 * @param strParamName
	 * @param strDefault
	 * @return
	 * 获取字符型参数 簡寫
	 */
	public String gpsv(String strParamName,String strDefault){
		return this.GetExtValue(strParamName,strDefault);
	}
	
	public void spsv(String strParamName, String paramvalue){
		this.SetValue(strParamName, paramvalue);
	}
	
	public boolean gpbv(String strParamName, boolean bDefault){
		return this.GetExtValue(strParamName,bDefault);
	}
	
	public void spbv(String strParamName, boolean paramvalue){
		this.SetValue(strParamName, (Object)paramvalue);
	}
	
	public int gpiv(String strParamName){
		return this.gpiv(strParamName,0);
	}
	
	public int gpiv(String strParamName, int nDefault){
		return this.GetExtValue(strParamName,nDefault);
	}
	
	public Object gpov(String strParamName){
		return this.GetExtValue(strParamName);
	}
	
	/**
	 * 设置参数值
	 * 
	 * @param strParamName
	 * @param objParamValue
	 */
	public void spov(String strParamName, Object paramvalue){
		this.SetExtValue(strParamName, paramvalue);
	}
}
